<?php
/**
 * Abstract class with common functionality for 
 * configure nested sets adapters.
 * 
 * @category   Zend
 * @package    Zend_Db
 * @author     Steshenko Alexander (http://lcf.name)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
abstract class Zend_Db_Tree_Nested_Adapter_Abstract 
    implements Zend_Db_Tree_Nested_Adapter_Interface
{

    /**
     * Default table's name of structure table
     *
     * @var string
     */
    protected static $_defaultTableName = null;
    
    /**
     * Default columns
     *
     * @var array
     */
    protected static $_defaultColumns;
    
    /**
     * Default aliases. 
     * In most cases we don't need anything except level.
     *
     * @var array
     */
    protected static $_defaultAliases = array(
        Zend_Db_Tree_Nested::ID        => null,
        Zend_Db_Tree_Nested::LEFT_KEY  => null,
        Zend_Db_Tree_Nested::RIGHT_KEY => null,
        Zend_Db_Tree_Nested::LEVEL     => 'level',
        Zend_Db_Tree_Nested::TREE_ID   => null,
    );
    
    /**
     * Default relative table identifier column key
     *
     * @var string
     */
    protected static $_defaultRelativeKey = null;
    
    /**
     * Current tree identificator
     *
     * @var integer
     */
    protected $_treeId = null;
    
    /**
     * Database Adapter
     *
     * @var Zend_Db_Adapter_Abstract
     */
    protected $_adapter = null;
    
    /**
     * Structure table's name
     *
     * @var string
     */
    protected $_tableName = null;
    
    /**
     * Structure table's columns' names
	 *
     * @var array
     */
    protected $_columns = null;
    
    /**
     * Structure table's columns' aliases
     *
     * @var array
     */
    protected $_aliases = null;
    
    /**
     * Relative table identifier column key.
     * Is used for callback delete.
     *
     * @var string
     */
    protected $_relativeKey = null;
    
    /**
     * Relative table. Is used for callback delete.
     *
     * @var string
     */
    protected $_relativeTableName = null;
        
    /**
     * Constructor.
     *
     * Supported params for $config are:
     * - db              = user-supplied instance of database connector,
     * - tableName       = table name.
     * - columns         = table columns
     * - aliases         = aliases for return-type queries
     * - relativeKey     = node id column in relative table
     * - treeId          = tree id
     * - relativeTableName   = relative table name
     *
     * @param  mixed $config Array of user-specified config options
     * @return void
     */
    public function __construct($config = array())
    {
        foreach ($config as $key => $value) {
            switch ($key) {
                case 'db':
                    $this->_adapter = $value;
                    break;
                case 'tableName':
                    $this->_tableName = (string) $value;
                    break;
                case 'columns':
                    $this->_columns = (array) $value;
                    break;
                case 'aliases':
                    $this->_aliases = (array) $value;
                    break;
                case 'relativeKey':
                    $this->_relativeKey = (string) $value;
                    break;
                case 'treeId':
                    $this->setTreeId((int) $value);
                    break;
                case 'relativeTableName':
                    $this->setRelativeTableName((string) $value);
            }
        }
        $this->_setup();
    }
    
    /**
     * Configuration of the adapter
     *
     */
    protected function _setup()
    {
        // setup database connection adapter
        if ($this->_adapter === null) {
            // try to obtain adapter from Zend_Db_Table
            $this->_adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
            if (!$this->_adapter instanceof Zend_Db_Adapter_Abstract) {
                throw new Zend_Db_Tree_Nested_Exception('No adapter found for ' . get_class($this));
            }
        }
        // setup table name
        if ($this->_tableName === null) {
            $this->_tableName = self::getDefaultTableName();
            if (!$this->_tableName) {
                throw new Zend_Db_Tree_Nested_Exception('Table name for ' 
                    . get_class($this) . ' is not specified');
            }
        }
        // setup columns
        if ($this->_columns === null) {
            $this->_columns = self::getDefaultColumns();
            if (count($this->_columns) != 5) {
                throw new Zend_Db_Tree_Nested_Exception('Incorrect columns values');
            }
        }
        // setup aliases
        if ($this->_aliases === null) {
            $this->_aliases = self::getDefaultAliases();
            if (count($this->_aliases) != 5) {
                throw new Zend_Db_Tree_Nested_Exception('Incorrect aliases values');
            }
        }
        // setup relative key
        if ($this->_relativeKey === null) {
            $this->_relativeKey = self::getDefaultRelativeKey();
        }
    }
    
    /**
     * Set default table name for all Zend_Db_Tree_Nested objects.
     * It will be used if other is not specified in constructor.
     *
     * @param string $tableName
     */
    public static function setDefaultTableName($tableName)
    {
        self::$_defaultTableName = $tableName;
    }
    
    /**
     * Returns default structure table's name
     *
     * @return string
     */
    public static function getDefaultTableName()
    {
        return self::$_defaultTableName;
    }
    
    /**
     * Set default columns for all objects.
     *
     * @param string $columns
     */
    public static function setDefaultColumns($columns)
    {
        self::$_defaultColumns = $columns;
    }
    
    /**
     * Return default columns array
     *
     * @return array
     */
    public static function getDefaultColumns()
    {
        return self::$_defaultColumns;
    }
    
    /**
     * Set default columns' aliases for all objects.
     *
     * @param string $aliases
     */
    public static function setDefaultAliases($aliases)
    {
        self::$_defaultAliases = $aliases;
    }
    
    /**
     * Returns default aliases array
     *
     * @return array
     */
    public static function getDefaultAliases()
    {
        return self::$_defaultAliases;
    }
    
    /**
     * Sets default relative table identifier's column
     *
     * @param string $key
     */
    public static function setDefaultRelativeKey($key)
    {
        self::$_defaultRelativeKey = $key;
    }
    
    /**
     * Returns default relative key
     *
     * @return string
     */
    public static function getDefaultRelativeKey()
    {
        return self::$_defaultRelativeKey;
    }
    
    /**
     * Sets tree id
     *
     * @param integer $treeId
     */
    public function setTreeId($treeId)
    {
        $this->_treeId = (int) $treeId;
    }
    
    /**
     * Sets name of relative table
     *
     * @param string $relativeTableName
     */
    public function setRelativeTableName($relativeTableName)
    {
        $this->_relativeTableName = (string) $relativeTableName;
    }
    
    /**
     * Set aliases for columns
     *
     * @param array $aliases
     */
    public function setAliases($aliases)
    {
        $this->_aliases = $aliases;
    }
    
    /**
     * Return aliases for columns
     *
     * @return array
     */
    public function getAliases()
    {
        return $this->_aliases;
    }
    
    /**
     * Returns columns for external joining
     *
     * @return string
     */
    public function getIdColumn()
    {
        return $this->_columns[Zend_Db_Tree_Nested::ID];
    }
    
    /**
     * Returns relative key column for external joining
     *
     * @return string
     */
    public function getRelativeKeyColumn()
    {
        return $this->_relativeKey;
    }
}